using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using PickGold.Charting;
using System.Web.UI.WebControls;

namespace PickGold.Charting.Utilities
{
	internal class BinaryFormatSerializer : SerializerBase
	{
		internal void CheckPropertiesID(ArrayList propNames)
		{
		}

		public void Deserialize(object objectToDeserialize, BinaryReader reader)
		{
			if (objectToDeserialize == null)
			{
				throw new ArgumentNullException("objectToDeserialize");
			}
			if (reader == null)
			{
				throw new ArgumentNullException("reader");
			}
			if (base.IsUnknownAttributeIgnored)
			{
				throw new InvalidOperationException(SR.ExceptionChartSerializerBinaryIgnoreUnknownAttributesUnsupported);
			}
			char[] chArray = reader.ReadChars(15);
			if (((chArray[0] != 'D') || (chArray[1] != 'C')) || ((chArray[2] != 'B') || (chArray[3] != 'F')))
			{
				throw new InvalidOperationException(SR.ExceptionChartSerializerBinaryFromatInvalid);
			}
			base.ReadHashID(reader);
			if (base.IsResetWhenLoading)
			{
				this.ResetObjectProperties(objectToDeserialize);
			}
			this.DeserializeObject(objectToDeserialize, null, base.GetObjectName(objectToDeserialize), reader, false);
		}

		public void Deserialize(object objectToDeserialize, Stream stream)
		{
			this.Deserialize(objectToDeserialize, new BinaryReader(stream));
		}

		internal override void Deserialize(object objectToDeserialize, object source)
		{
			if (objectToDeserialize == null)
			{
				throw new ArgumentNullException("objectToDeserialize");
			}
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			string fileName = source as string;
			if (fileName != null)
			{
				this.Deserialize(objectToDeserialize, fileName);
			}
			else
			{
				Stream stream = source as Stream;
				if (stream != null)
				{
					this.Deserialize(objectToDeserialize, stream);
				}
				else
				{
					BinaryWriter writer = source as BinaryWriter;
					if (writer == null)
					{
						throw new ArgumentException(SR.ExceptionChartSerializerSourceObjectInvalid, "source");
					}
					this.Deserialize(objectToDeserialize, writer);
				}
			}
		}

		public void Deserialize(object objectToDeserialize, string fileName)
		{
			FileStream input = new FileStream(fileName, FileMode.Open);
			this.Deserialize(objectToDeserialize, new BinaryReader(input));
			input.Close();
		}

		protected virtual int DeserializeObject(object objectToDeserialize, object parent, string elementName, BinaryReader reader, bool skipElement)
		{
			int num = 0;
			if (objectToDeserialize != null)
			{
				Type[] exportedTypes = null;
				int num2 = 0;
				IList list = objectToDeserialize as IList;
				if (list != null)
				{
					short num3 = 0;
					PropertyInfo property = objectToDeserialize.GetType().GetProperty("Item", new Type[] { typeof(int) });
					while ((num3 = base.ReadHashID(reader)) != 0)
					{
						string itemTypeName = string.Empty;
						if (property != null)
						{
							if (SerializerBase.GetStringHashCode(property.PropertyType.Name) == num3)
							{
								itemTypeName = property.PropertyType.Name;
							}
							else
							{
								Assembly assembly = property.PropertyType.Assembly;
								if (assembly != null)
								{
									if (exportedTypes == null)
									{
										exportedTypes = assembly.GetExportedTypes();
									}
									foreach (Type type in exportedTypes)
									{
										if (type.IsSubclassOf(property.PropertyType) && (SerializerBase.GetStringHashCode(type.Name) == num3))
										{
											itemTypeName = type.Name;
											break;
										}
									}
								}
							}
						}
						string itemName = null;
						bool reusedObject = false;
						object obj2 = base.GetListNewItem(list, itemTypeName, ref itemName, ref reusedObject);
						int num4 = this.DeserializeObject(obj2, objectToDeserialize, "", reader, skipElement);
						if (!skipElement && ((num4 > 0) || reusedObject))
						{
							list.Insert(num2++, obj2);
						}
						num += num4;
					}
					return num;
				}
				PropertyInfo[] properties = objectToDeserialize.GetType().GetProperties();
				if (properties == null)
				{
					return num;
				}
				PropertyInfo pi = null;
				while ((pi = this.ReadPropertyInfo(objectToDeserialize, parent, properties, reader)) != null)
				{
					if (base.ShouldSerializeAsAttribute(pi, objectToDeserialize))
					{
						if (this.SetPropertyValue(objectToDeserialize, pi, reader, skipElement))
						{
							num++;
						}
					}
					else
					{
						PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToDeserialize)[pi.Name];
						if (descriptor != null)
						{
							object obj3 = descriptor.GetValue(objectToDeserialize);
							num += this.DeserializeObject(obj3, objectToDeserialize, pi.Name, reader, !base.IsSerializableContent(pi.Name, objectToDeserialize));
							continue;
						}
						if (!base.IsUnknownAttributeIgnored)
						{
							throw new InvalidOperationException(SR.ExceptionChartSerializerPropertyNameUnknown(pi.Name, objectToDeserialize.GetType().ToString()));
						}
					}
				}
			}
			return num;
		}

		private PropertyInfo ReadPropertyInfo(object objectToDeserialize, object parent, PropertyInfo[] properties, BinaryReader reader)
		{
			short num = base.ReadHashID(reader);
			if (num == 0)
			{
				return null;
			}
			foreach (PropertyInfo info in properties)
			{
				if (!base.IsChartBaseProperty(objectToDeserialize, parent, info))
				{
					if (info.CanRead && (info.PropertyType.GetInterface("ICollection", true) != null))
					{
						if (SerializerBase.GetStringHashCode(info.Name) == num)
						{
							return info;
						}
					}
					else if ((info.CanRead && info.CanWrite) && (!(info.Name == "Item") && (SerializerBase.GetStringHashCode(info.Name) == num)))
					{
						return info;
					}
				}
			}
			throw new InvalidOperationException(SR.ExceptionChartSerializerPropertyNotFound);
		}

		internal void Serialize(object objectToSerialize, BinaryWriter writer)
		{
			if (objectToSerialize == null)
			{
				throw new ArgumentNullException("objectToSerialize");
			}
			if (writer == null)
			{
				throw new ArgumentNullException("writer");
			}
			char[] chars = new char[] { 'D', 'C', 'B', 'F', '4', '0', '0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
			writer.Write(chars);
			this.SerializeObject(objectToSerialize, null, base.GetObjectName(objectToSerialize), writer);
			writer.Flush();
			writer.Seek(0, SeekOrigin.Begin);
		}

		internal void Serialize(object objectToSerialize, Stream stream)
		{
			this.Serialize(objectToSerialize, new BinaryWriter(stream));
		}

		internal override void Serialize(object objectToSerialize, object destination)
		{
			if (objectToSerialize == null)
			{
				throw new ArgumentNullException("objectToSerialize");
			}
			if (destination == null)
			{
				throw new ArgumentNullException("destination");
			}
			string fileName = destination as string;
			if (fileName != null)
			{
				this.Serialize(objectToSerialize, fileName);
			}
			else
			{
				Stream stream = destination as Stream;
				if (stream != null)
				{
					this.Serialize(objectToSerialize, stream);
				}
				else
				{
					BinaryWriter writer = destination as BinaryWriter;
					if (writer == null)
					{
						throw new ArgumentException(SR.ExceptionChartSerializerDestinationObjectInvalid, "destination");
					}
					this.Serialize(objectToSerialize, writer);
				}
			}
		}

		internal void Serialize(object objectToSerialize, string fileName)
		{
			FileStream output = new FileStream(fileName, FileMode.Create);
			this.Serialize(objectToSerialize, new BinaryWriter(output));
			output.Close();
		}

		internal virtual void SerializeCollection(object objectToSerialize, string elementName, BinaryWriter writer)
		{
			ICollection is2 = objectToSerialize as ICollection;
			if (is2 != null)
			{
				writer.Write(SerializerBase.GetStringHashCode(elementName));
				long num = writer.Seek(0, SeekOrigin.Current);
				foreach (object obj2 in is2)
				{
					if (obj2 is DataPoint)
					{
						this.SerializeDataPoint(obj2, base.GetObjectName(obj2), writer);
					}
					else
					{
						this.SerializeObject(obj2, objectToSerialize, base.GetObjectName(obj2), writer);
					}
				}
				if (writer.Seek(0, SeekOrigin.Current) == num)
				{
					writer.Seek(-2, SeekOrigin.Current);
					writer.Write((short)0);
					writer.Seek(-2, SeekOrigin.Current);
				}
				else
				{
					writer.Write((short)0);
				}
			}
		}

		private void SerializeDataPoint(object objectToSerialize, string elementName, BinaryWriter writer)
		{
			writer.Write(SerializerBase.GetStringHashCode(elementName));
			long num = writer.Seek(0, SeekOrigin.Current);
			DataPoint parent = objectToSerialize as DataPoint;
			if ((parent.XValue != 0.0) && base.IsSerializableContent("XValue", objectToSerialize))
			{
				this.SerializeProperty(parent.XValue, parent, "XValue", writer);
			}
			if ((parent.YValues.Length > 0) && base.IsSerializableContent("YValues", objectToSerialize))
			{
				this.SerializeProperty(parent.YValues, parent, "YValues", writer);
			}
			if (parent.IsEmpty && base.IsSerializableContent("IsEmpty", objectToSerialize))
			{
				this.SerializeProperty(parent.IsEmpty, parent, "IsEmpty", writer);
			}
			bool flag = false;
			foreach (DictionaryEntry entry in parent.properties)
			{
				if (entry.Key is int)
				{
					string propertyName = ((CommonCustomProperties)((int)entry.Key)).ToString();
					if (base.IsSerializableContent(propertyName, objectToSerialize))
					{
						this.SerializeProperty(entry.Value, parent, propertyName, writer);
					}
				}
				else
				{
					flag = true;
				}
			}
			if ((flag && !string.IsNullOrEmpty(parent.CustomProperties)) && base.IsSerializableContent("CustomProperties", objectToSerialize))
			{
				this.SerializeProperty(parent.CustomProperties, parent, "CustomProperties", writer);
			}
			if (writer.Seek(0, SeekOrigin.Current) == num)
			{
				writer.Seek(-2, SeekOrigin.Current);
				writer.Write((short)0);
				writer.Seek(-2, SeekOrigin.Current);
			}
			else
			{
				writer.Write((short)0);
			}
		}

		internal virtual void SerializeObject(object objectToSerialize, object parent, string elementName, BinaryWriter writer)
		{
			if (objectToSerialize != null)
			{
				if (parent != null)
				{
					PropertyDescriptor descriptor = TypeDescriptor.GetProperties(parent)[elementName];
					if (descriptor != null)
					{
						SerializationVisibilityAttribute attribute = (SerializationVisibilityAttribute)descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
						if ((attribute != null) && (attribute.Visibility == SerializationVisibility.Hidden))
						{
							return;
						}
					}
				}
				if (objectToSerialize is ICollection)
				{
					this.SerializeCollection(objectToSerialize, elementName, writer);
				}
				else
				{
					writer.Write(SerializerBase.GetStringHashCode(elementName));
					long num = writer.Seek(0, SeekOrigin.Current);
					ArrayList propNames = new ArrayList();
					PropertyInfo[] properties = objectToSerialize.GetType().GetProperties();
					if (properties != null)
					{
						foreach (PropertyInfo info in properties)
						{
							if (!base.IsChartBaseProperty(objectToSerialize, parent, info))
							{
								if ((info.CanRead && (info.PropertyType.GetInterface("ICollection", true) != null)) && !base.SerializeICollAsAtribute(info, objectToSerialize))
								{
									bool flag = base.IsSerializableContent(info.Name, objectToSerialize);
									if (flag && (objectToSerialize != null))
									{
										PropertyDescriptor descriptor2 = TypeDescriptor.GetProperties(objectToSerialize)[info.Name];
										if (descriptor2 != null)
										{
											SerializationVisibilityAttribute attribute2 = (SerializationVisibilityAttribute)descriptor2.Attributes[typeof(SerializationVisibilityAttribute)];
											if ((attribute2 != null) && (attribute2.Visibility == SerializationVisibility.Hidden))
											{
												flag = false;
											}
										}
									}
									MethodInfo method = objectToSerialize.GetType().GetMethod("ShouldSerialize" + info.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
									if (flag && (method != null))
									{
										object obj2 = method.Invoke(objectToSerialize, null);
										if ((obj2 is bool) && !((bool)obj2))
										{
											flag = false;
										}
									}
									if (flag)
									{
										propNames.Add(info.Name);
										this.SerializeCollection(info.GetValue(objectToSerialize, null), info.Name, writer);
									}
								}
								else if ((info.CanRead && info.CanWrite) && (info.Name != "Item"))
								{
									if (base.IsSerializableContent(info.Name, objectToSerialize))
									{
										if (base.ShouldSerializeAsAttribute(info, objectToSerialize))
										{
											this.SerializeProperty(info.GetValue(objectToSerialize, null), objectToSerialize, info.Name, writer);
										}
										else
										{
											this.SerializeObject(info.GetValue(objectToSerialize, null), objectToSerialize, info.Name, writer);
										}
									}
									propNames.Add(info.Name);
								}
							}
						}
						this.CheckPropertiesID(propNames);
					}
					if (writer.Seek(0, SeekOrigin.Current) == num)
					{
						writer.Seek(-2, SeekOrigin.Current);
						writer.Write((short)0);
						writer.Seek(-2, SeekOrigin.Current);
					}
					else
					{
						writer.Write((short)0);
					}
				}
			}
		}

		internal virtual void SerializeProperty(object objectToSerialize, object parent, string elementName, BinaryWriter writer)
		{
			if ((objectToSerialize != null) && (parent != null))
			{
				PropertyDescriptor descriptor = TypeDescriptor.GetProperties(parent)[elementName];
				if (descriptor != null)
				{
					DefaultValueAttribute attribute = (DefaultValueAttribute)descriptor.Attributes[typeof(DefaultValueAttribute)];
					if (attribute != null)
					{
						if (objectToSerialize.Equals(attribute.Value))
						{
							return;
						}
					}
					else
					{
						MethodInfo method = parent.GetType().GetMethod("ShouldSerialize" + elementName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
						if (method != null)
						{
							object obj2 = method.Invoke(parent, null);
							if ((obj2 is bool) && !((bool)obj2))
							{
								return;
							}
						}
					}
					SerializationVisibilityAttribute attribute2 = (SerializationVisibilityAttribute)descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
					if ((attribute2 != null) && (attribute2.Visibility == SerializationVisibility.Hidden))
					{
						return;
					}
				}
				this.WritePropertyValue(objectToSerialize, elementName, writer);
			}
		}

		private bool SetPropertyValue(object obj, PropertyInfo pi, BinaryReader reader, bool skipElement)
		{
			if (pi != null)
			{
				object obj2 = null;
				if (pi.PropertyType == typeof(bool))
				{
					obj2 = reader.ReadBoolean();
				}
				else if (pi.PropertyType == typeof(double))
				{
					obj2 = reader.ReadDouble();
				}
				else if (pi.PropertyType == typeof(string))
				{
					obj2 = reader.ReadString();
				}
				else if (pi.PropertyType == typeof(int))
				{
					obj2 = reader.ReadInt32();
				}
				else if (pi.PropertyType == typeof(long))
				{
					obj2 = reader.ReadInt64();
				}
				else if (pi.PropertyType == typeof(float))
				{
					obj2 = reader.ReadSingle();
				}
				else if (pi.PropertyType.IsEnum)
				{
					obj2 = Enum.Parse(pi.PropertyType, reader.ReadString());
				}
				else if (pi.PropertyType == typeof(byte))
				{
					obj2 = reader.ReadByte();
				}
				else if (pi.PropertyType == typeof(Unit))
				{
					obj2 = new Unit(reader.ReadDouble());
				}
				else if (pi.PropertyType == typeof(Font))
				{
					obj2 = SerializerBase.FontFromString(reader.ReadString());
				}
				else if (pi.PropertyType == typeof(Color))
				{
					obj2 = Color.FromArgb(reader.ReadInt32());
				}
				else if (pi.PropertyType == typeof(DateTime))
				{
					obj2 = new DateTime(reader.ReadInt64());
				}
				else if (pi.PropertyType == typeof(Size))
				{
					obj2 = new Size(reader.ReadInt32(), reader.ReadInt32());
				}
				else if (pi.PropertyType == typeof(Margins))
				{
					obj2 = new Margins(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
				}
				else if (pi.PropertyType == typeof(double[]))
				{
					double[] numArray = new double[reader.ReadInt32()];
					for (int i = 0; i < numArray.Length; i++)
					{
						numArray[i] = reader.ReadDouble();
					}
					obj2 = numArray;
				}
				else if (pi.PropertyType == typeof(Color[]))
				{
					Color[] colorArray = new Color[reader.ReadInt32()];
					for (int j = 0; j < colorArray.Length; j++)
					{
						colorArray[j] = Color.FromArgb(reader.ReadInt32());
					}
					obj2 = colorArray;
				}
				else
				{
					if (pi.PropertyType != typeof(System.Drawing.Image))
					{
						throw new InvalidOperationException(SR.ExceptionChartSerializerBinaryTypeUnsupported(obj.GetType().ToString()));
					}
					int count = reader.ReadInt32();
					MemoryStream stream = new MemoryStream(count + 10);
					stream.Write(reader.ReadBytes(count), 0, count);
					obj2 = new Bitmap(System.Drawing.Image.FromStream(stream));
					stream.Close();
				}
				if (!skipElement && base.IsSerializableContent(pi.Name, obj))
				{
					pi.SetValue(obj, obj2, null);
					return true;
				}
			}
			return false;
		}

		internal void WritePropertyValue(object obj, string elementName, BinaryWriter writer)
		{
			writer.Write(SerializerBase.GetStringHashCode(elementName));
			if (obj is bool)
			{
				writer.Write((bool)obj);
			}
			else if (obj is double)
			{
				writer.Write((double)obj);
			}
			else if (obj is string)
			{
				writer.Write((string)obj);
			}
			else if (obj is int)
			{
				writer.Write((int)obj);
			}
			else if (obj is long)
			{
				writer.Write((long)obj);
			}
			else if (obj is float)
			{
				writer.Write((float)obj);
			}
			else if (obj.GetType().IsEnum)
			{
				string str = obj.ToString();
				writer.Write(str);
			}
			else if (obj is byte)
			{
				writer.Write((byte)obj);
			}
			else if (obj is Unit)
			{
				Unit unit = (Unit)obj;
				writer.Write(unit.Value);
			}
			else if (obj is Font)
			{
				writer.Write(SerializerBase.FontToString((Font)obj));
			}
			else if (obj is Color)
			{
				writer.Write(((Color)obj).ToArgb());
			}
			else if (obj is DateTime)
			{
				DateTime time = (DateTime)obj;
				writer.Write(time.Ticks);
			}
			else if (obj is Size)
			{
				Size size = (Size)obj;
				writer.Write(size.Width);
				Size size2 = (Size)obj;
				writer.Write(size2.Height);
			}
			else if (obj is double[])
			{
				double[] numArray = (double[])obj;
				writer.Write(numArray.Length);
				foreach (double num in numArray)
				{
					writer.Write(num);
				}
			}
			else if (obj is Color[])
			{
				Color[] colorArray = (Color[])obj;
				writer.Write(colorArray.Length);
				foreach (Color color in colorArray)
				{
					writer.Write(color.ToArgb());
				}
			}
			else if (obj is System.Drawing.Image)
			{
				MemoryStream stream = new MemoryStream();
				((System.Drawing.Image)obj).Save(stream, ((System.Drawing.Image)obj).RawFormat);
				int num2 = (int)stream.Seek(0L, SeekOrigin.End);
				stream.Seek(0L, SeekOrigin.Begin);
				writer.Write(num2);
				writer.Write(stream.ToArray());
				stream.Close();
			}
			else
			{
				if (!(obj is Margins))
				{
					throw new InvalidOperationException(SR.ExceptionChartSerializerBinaryTypeUnsupported(obj.GetType().ToString()));
				}
				writer.Write(((Margins)obj).Top);
				writer.Write(((Margins)obj).Bottom);
				writer.Write(((Margins)obj).Left);
				writer.Write(((Margins)obj).Right);
			}
		}
	}
}

